﻿namespace Sustainalytics.Portfolios.Servive.Tests
{
    using System;
    using System.Net;
    using System.Net.Http;
    using System.Threading.Tasks;
    using System.Web.Http;
    using System.Web.Http.Controllers;
    using System.Web.Http.Dispatcher;

    using FakeItEasy;

    using Microsoft.Owin.Testing;

    using Owin;

    using Sustainalytics.Claims;
    using Sustainalytics.Portfolios.Service;
    using Sustainalytics.Portfolios.Service.Infrastructure;
    using Sustainalytics.Portfolios.Service.Utility;

    using Xunit;


    public class OwinExceptionHandling
    {
        private readonly Uri _uri = new Uri("http://testserver/api/v1/portfolios/");

        private void CreateConfiguration(IAppBuilder appBuilder, IHttpControllerActivator compositionRoot, bool validation)
        {
            using (var config = new HttpConfiguration())
            {
                appBuilder.Use<OwinExceptionMiddleware>();
                config.Services.Replace(typeof(IHttpControllerActivator), compositionRoot);

                config.Routes.MapHttpRoute(
                    name: "ApiById",
                    routeTemplate: "api/{controller}/{id}",
                    defaults: new { id = RouteParameter.Optional },
                    constraints: new { id = @"^[0-9]+$" });
                WebApiConfig.Register(config);
                config.Filters.Add(new CustomExceptionFilter());
                var fakeClaimsChecker = A.Fake<IClaimsChecker>();
                PortfolioClaimsCheckerExtensions.ApiControllerValidator = (checker, controller, arg3) => validation;
                config.Filters.Add(new ClaimFilter(fakeClaimsChecker));
                config.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
                appBuilder.UseWebApi(config);
                config.EnsureInitialized();
            }
        }


        [Fact]
        public async Task When_Controller_Instantiation_Throws_Exception_Server_returns_500()
        {
            var fakeCompositionRoot = A.Fake<IHttpControllerActivator>();
            A.CallTo(
                () => fakeCompositionRoot.Create(A<HttpRequestMessage>._, A<HttpControllerDescriptor>._, A<Type>._))
                .Throws<Exception>();

            using (var server = TestServer.Create(app => this.CreateConfiguration(app, fakeCompositionRoot, true)))
            {
                var httpclient = new HttpClient(server.Handler);
                var uri = string.Format("{0}{1}", _uri, "ADA34C15-82B7-4C05-90CB-B2EC4D43B481");

                HttpResponseMessage response = await httpclient.DeleteAsync(uri).ConfigureAwait(false);
                Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
            }
        }

        [Fact]
        public async Task When_Controller_Instantiation_Controller_not_found_Server_returns_404()
        {
            var fakeCompositionRoot = A.Fake<IHttpControllerActivator>();
            A.CallTo(
                () => fakeCompositionRoot.Create(A<HttpRequestMessage>._, A<HttpControllerDescriptor>._, A<Type>._))
                .Returns(null);
            using (TestServer server = TestServer.Create(app => this.CreateConfiguration(app, fakeCompositionRoot, true)))
            {
                var httpclient = new HttpClient(server.Handler);
                var uri = string.Format("{0}{1}", _uri, "ADA34C15-82B7-4C05-90CB-B2EC4D43B481");

                HttpResponseMessage response = await httpclient.DeleteAsync(uri).ConfigureAwait(false);
                Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
            }
        }
    }
}